﻿using System;
using System.Threading;
using Instances.Contracts;
using Microsoft.HomeServer.SDK.Interop.v1;
using WhsFacebook.Net.Contracts;

namespace WhsFacebook.Whs.Service
{
    public sealed class UpdateChecker
    {
        private static readonly UpdateChecker _instance = new UpdateChecker();

        public static UpdateChecker Instance
        {
            get { return _instance; }
        }

        private readonly log4net.ILog _log = log4net.LogManager.GetLogger(typeof(UpdateChecker));
        private Timer _timer;
        private readonly object _checkLock = new object();
        private readonly WhsNotification _notification;

        public DateTime LastCheck
        {
            get;
            private set;
        }

        public ReleaseInfo NewVersion
        {
            get;
            private set;
        }

        private void OnTick(object state)
        {
            try
            {
                DoCheck();
            }
            catch (Exception x)
            {
                _log.Warn("Failed to check for update", x);
            }
        }

        public void DoCheckManually()
        {
            _log.Info("Checking for update manually...");

            try
            {
                DoCheck();
            }
            catch (Exception x)
            {
                _log.Error("Failed to check for update manually", x);

                throw;
            }
        }

        private void DoCheck()
        {
            lock (_checkLock)
            {
                try
                {
                    if (_log.IsDebugEnabled)
                    {
                        _log.DebugFormat(
                            "Checking for update for {0} (#{1})...",
                            WhsFacebookVersion.VersionString,
                            WhsFacebookVersion.VersionId
                            );
                    }

                    using (var wsc = new WhsFacebookServiceClientFactory())
                    {
                        var q = new LatestVersionQuery()
                                    {
                                        ProductId = WhsFacebookVersion.ProductId,
                                        CurrentVersionId = WhsFacebookVersion.VersionId,
                                        InstanceId = WhsFacebookRegistry.GetInstanceId(),
                                    };

                        var nv = wsc.CreateChannel().GetLatestVersion(q);

                        if ((nv.ReleaseId > WhsFacebookVersion.VersionId))
                            this.NewVersion = nv;
                        else
                            this.NewVersion = null;
                    }
	
                    // store this check
                    this.LastCheck = DateTime.Now;
	
                    Properties.States.Default.CheckUpdateLastCheck = this.LastCheck;
	
                    Properties.States.Default.Save();
	
                    // finalize
                    if (this.NewVersion == null)
                    {
                        _log.Info("No new update found");

                        _notification.HideNotification();
                    }
                    else
                    {
                        _log.Info("Update found: " + this.NewVersion.VersionString);

                        _notification.Title = string.Format(
                            Properties.Resources.txtUpdateAvailableNotificationTitle,
                            this.NewVersion.VersionString
                            );

                        _notification.Description = string.Format(
                            Properties.Resources.txtUpdateAvailableNotificationDesc,
                            this.NewVersion.VersionString
                            );

                        _notification.ShowNotification();
                    }
                }
                catch (Exception e)
                {
                    _log.Error("Failed to check for update", e);

                    throw;
                }
            }
        }

        private UpdateChecker()
        {
            if (_log.IsDebugEnabled)
                _log.Debug("Creating singleton");

            try
            {
                // notification
                _notification = new WhsNotification(Whs.Properties.Constants.UpdateNotificationId)
                                    {
                                        Severity = WHS_Notification_Severity.WHS_WARNING
                                    };

                // load state
                try
                {
                    this.LastCheck = Properties.States.Default.CheckUpdateLastCheck;
                }
                catch
                {
                    _log.Warn("Failed to read CheckUpdateLastCheck state");
	
                    this.LastCheck = DateTime.MinValue;
                }
	
                // initialize update check timer
                _timer = new Timer(
                    new TimerCallback(OnTick),
                    null,
                    1000,
                    (1000 * 60 * Properties.Settings.Default.CheckUpdateIntervalMinutes)
                    );
            }
            catch (Exception e)
            {
                _log.Fatal("Failed to create singleton", e);

                throw;
            }

        }
    }
}